
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>


int createXml()
{
    xmlDocPtr doc = xmlNewDoc(BAD_CAST"1.0");

	xmlNodePtr root_node = xmlNewNode(NULL, BAD_CAST"root");
    xmlDocSetRootElement(doc,root_node);

    xmlNewTextChild(root_node, NULL, BAD_CAST"node1", BAD_CAST"node1 content");
    xmlNewTextChild(root_node, NULL, BAD_CAST"node2", BAD_CAST"node2 content");
    xmlNewTextChild(root_node, NULL, BAD_CAST"node3", BAD_CAST"node3 content");

    xmlNodePtr node = xmlNewNode(NULL, BAD_CAST"node4");
    xmlAddChild(node, xmlNewText(BAD_CAST"node4 content"));
    xmlNewProp(node, BAD_CAST"attr1", BAD_CAST"yes");
    xmlAddChild(root_node, node);

    node = xmlNewNode(NULL, BAD_CAST"node5");
    xmlAddChild(node, xmlNewText(BAD_CAST"node5 content"));
    xmlNewProp(node, BAD_CAST"attr2", BAD_CAST"yes");
    xmlAddChild(root_node, node);

    node = xmlNewNode(NULL, BAD_CAST"node6");
    xmlAddChild(root_node, node);
    xmlNodePtr leaf = xmlNewNode(NULL, BAD_CAST"leaf1");
    xmlAddChild(node, leaf);
    xmlAddChild(leaf, xmlNewText(BAD_CAST "leaf1 content"));

    int ret = xmlSaveFile("libxml-demo.xml", doc);
    if (ret != -1)
		printf("create file succ, write %d byte\n", ret);

    xmlFreeDoc(doc);
    return 0;
}


int modifyXml()
{
    xmlDocPtr doc;     
    xmlNodePtr curNode;
    xmlChar *str;          

    doc = xmlReadFile("libxml-demo.xml","GB2312", XML_PARSE_RECOVER);
    if (NULL == doc)
    {  
        printf("read file error\n");    
        return 1;
    }

    curNode = xmlDocGetRootElement(doc);
    if (NULL == curNode)
    {
        printf("read empty document\n");
        xmlFreeDoc(doc);
        return 2;
    }

    if (xmlStrcmp(curNode->name, BAD_CAST"root") != 0)
    {
        printf("root node != root");
        xmlFreeDoc(doc);
        return 3;
    }

    curNode = curNode->xmlChildrenNode;
    xmlNodePtr propNodePtr = NULL;
    while(curNode != NULL)
    {
        str = xmlNodeGetContent(curNode);
        printf("%s content: %s\n", curNode->name, str);
        xmlFree(str);

        if (xmlHasProp(curNode, BAD_CAST"attr2"))
        {
			propNodePtr = curNode;
		    break;
        }

        curNode = curNode->next;
    }

	if (propNodePtr == NULL)
    {
        printf("find attr2 error\n");
        xmlFreeDoc(doc);
        return 4;
    }

	xmlChar* attr = xmlGetProp(propNodePtr, BAD_CAST"attr2");
	printf("attr2 value: %s\n", attr);

    int ret = xmlSaveFile("libxml-demo.xml", doc);
    if (ret != -1)
		printf("modify file succ, write %d byte\n", ret);

    xmlFreeDoc(doc);
    return 0;
}


int xpathDemo()
{
    xmlXPathContextPtr context;
    xmlXPathObjectPtr  object;

    xmlDocPtr doc = xmlReadFile("libxml-demo.xml","GB2312", XML_PARSE_RECOVER);
    if (doc == NULL)
    {  
        printf("read file error\n");    
        return 1;
    }

    context = xmlXPathNewContext(doc);
    if (context == NULL)
    {  
       printf("create contex error\n");
       return 2;
    }

    object = xmlXPathEvalExpression(BAD_CAST"/root/node6/leaf1", context);
    if (object == NULL)
    {
       printf("find path error\n");
       return 3; 
    }

	xmlNodeSetPtr nodeSet = object->nodesetval;
	if (xmlXPathNodeSetIsEmpty(nodeSet))
	{
       printf("node set empty\n");
       return 4; 
	}

	for(int i=0; i<nodeSet->nodeNr; i++) 
	{
		printf("find node: %s\n", nodeSet->nodeTab[i]->name);
	}

    xmlXPathFreeObject(object);
    xmlXPathFreeContext(context);
	xmlFreeDoc(doc);
    return 0;    
}


int main()
{
	int ret;

	LIBXML_TEST_VERSION
	xmlInitParser();

	ret = createXml();
	ret = modifyXml();
	ret = xpathDemo();

	xmlCleanupParser();
	xmlMemoryDump();

	getchar();
	return 0;
}

